package pers.mihao.quickstream.common.util.spring;

import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.condition.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import pers.mihao.quickstream.common.util.ReflectionUtil;

import java.lang.reflect.Method;

/**
 * spring 动态注册controller的服务
 * @author mihao
 * @since 2023/1/12
 */
public class SpringRequestMappingRegister {

    private static RequestMappingHandlerMapping requestMappingHandlerMapping;

    private static Method register;

    private static Object mappingRegistry;

    private void init() {
        if (mappingRegistry == null) {
            synchronized (SpringRequestMappingRegister.class) {
                if (mappingRegistry == null) {
                    requestMappingHandlerMapping = ApplicationContextHolder.getBean(RequestMappingHandlerMapping.class);
                    mappingRegistry = ReflectionUtil.getValueByFieldName(requestMappingHandlerMapping, "mappingRegistry");
                    register = ReflectionUtil.getMethod(mappingRegistry.getClass(), "register",
                            Object.class, Object.class, Method.class);
                }
            }

        }
    }

    /**
     *
     * @param beanName beanName
     * @param method 方法
     * @param patterns 匹配
     * @param requestMethod
     */
    protected void registerRequestMapping(String beanName, Method method, String patterns, RequestMethod requestMethod) {
        this.init();
        PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition(patterns);
        RequestMethodsRequestCondition requestMethodsRequestCondition =
                new RequestMethodsRequestCondition(requestMethod);
        ParamsRequestCondition paramsRequestCondition = new ParamsRequestCondition();
        HeadersRequestCondition headersRequestCondition = new HeadersRequestCondition();
        ConsumesRequestCondition consumesRequestCondition = new ConsumesRequestCondition();
        ProducesRequestCondition producesRequestCondition = new ProducesRequestCondition();
        RequestMappingInfo requestMappingInfo = new RequestMappingInfo(patternsRequestCondition,
                requestMethodsRequestCondition, paramsRequestCondition, headersRequestCondition,
                consumesRequestCondition, producesRequestCondition, null);
        doRegister(beanName, method, requestMappingInfo);
    }

    protected void doRegister(String beanName, Method method, RequestMappingInfo requestMappingInfo) {
        this.init();
        try {
            register.invoke(mappingRegistry, requestMappingInfo, beanName, method);
        } catch (Exception e) {
            // DONOING
        }
    }
}
